package jdk8.lambda.lambda2;

import org.junit.Test;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 方法引用的使用
 * 1.使用情景：当要传递给 Lambda 体的操作，以及有了实现的方法了，可以使用方法引用
 * 2.方法引用，本质上就是Lambda表达式，而 Lambda 表达式作为函数式接口的实例。所以
 * 方法引用，也是函数式接口的实例
 *
 * 3.使用格式：类(或对象) :: 方法名
 *
 * 4.具体分为如下三种情况：
 *   情况一  对象 :: 非静态方法
 *   情况二	 类 :: 静态方法
 *   情况三  类 :: 非静态方法
 *
 * 5.方法引用使用的要求：要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的
 *   形参列表和返回值类型相同（针对于情况一和情况二）
 *
 */
public class MethodRefTest {

	// 情况一：对象 :: 实例方法
	//Consumer中的void accept(T t)
	//PrintStream中的void println(T t)
	@Test
	public void test1() {
		Consumer<String> consumer = t -> System.out.println(t);
		consumer.accept("北京");

		System.out.println("*********************");

		PrintStream ps = System.out;
		Consumer<String> consumer1 = System.out::println;
		consumer1.accept("长沙");
	}
	
	//Supplier中的T get()
	//Employee中的String getName()
	@Test
	public void test2() {
		Employee employee = new Employee(1001, "Tom", 23, 30000);
		Supplier<String> sup1 = () -> employee.getName();
		String s = sup1.get();
		System.out.println(s);

		System.out.println("*****************");

		Supplier<String> sup2 = employee::getName;
		System.out.println(sup2.get());
	}

	// 情况二：类 :: 静态方法
	//Comparator中的int compare(T t1,T t2)
	//Integer中的int compare(T t1,T t2)
	@Test
	public void test3() {
		Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2);
		System.out.println(com1.compare(23, 12));

		System.out.println("************************");

		Comparator<Integer> com2 = Integer::compare;
		System.out.println(com2.compare(23, 23));
	}
	
	//Function中的R apply(T t)
	//Math中的Long round(Double d)
	@Test
	public void test4() {
		//把 Double 转换为 Long
		Function<Double, Long> func1 = d -> Math.round(d);
		System.out.println(func1.apply(23.6));

		System.out.println("**********************");

		Function<Double, Long> func2 = Math::round;
		System.out.println(func2.apply(234.234234));
	}

	// 情况三：类 :: 实例方法 
	// Comparator中的int comapre(T t1,T t2)
	// String中的int t1.compareTo(t2)
	@Test
	public void test5() {
		Comparator<Integer> com1 = (o1, o2) -> o1.compareTo(o2);
		System.out.println(com1.compare(23, 12));

		Comparator<Integer> com2 = Integer::compareTo;
		System.out.println(com2.compare(12, 23));

		Comparator<String> com3 = String::compareTo;
		System.out.println(com3.compare("abc", "abe"));
	}

	//BiPredicate中的boolean test(T t1, T t2);
	//String中的boolean t1.equals(t2)
	@Test
	public void test6() {
		//传入两个参数，比较是否相同
		BiPredicate<String, String> pre1 = (t1, t2) -> t1.equals(t2);
		System.out.println(pre1.test("sdf", "sdf"));

		BiPredicate<String, String> pre2 = String::equals;
		System.out.println(pre2.test("sdF", "sdf"));
	}
	
	// Function中的R apply(T t)
	// Employee中的String getName();
	@Test
	public void test7() {

		Function<Employee, String> fun1 = t -> t.getName();
		System.out.println(fun1.apply(new Employee(101, "Tom", 21, 9000)));

		Function<Employee, String> fun2 = Employee::getName;
		System.out.println(fun2.apply(new Employee(102, "Jerry", 22, 19000)));

	}

}
